#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
智能人脸追踪系统 - 统一MCP服务器入口
Intelligent Face Tracker System - Unified MCP Server Entry Point

这个文件是整个系统的统一入口点，负责：
1. 启动Web服务（Flask应用）
2. 启动MCP服务（FastMCP服务器）
3. 协调两个服务的生命周期管理
4. 提供统一的配置和日志管理
"""

import asyncio
import logging
import signal
import socket
import sys
import threading
import time
from pathlib import Path
from typing import Optional

# 添加项目根目录到Python路径
project_root = Path(__file__).parent.parent
if str(project_root) not in sys.path:
    sys.path.insert(0, str(project_root))

from face_tracker_mcp.config import load_config, setup_logging
from face_tracker_mcp.services import WebService, MCPService
from face_tracker_mcp.core.detection import YOLO11_FaceDetect

logger = logging.getLogger("FaceTrackerMCP")


def get_local_ips():
    """获取本机所有局域网IP地址"""
    import subprocess
    ips = []

    try:
        # 使用ip命令获取所有网络接口的IP地址
        result = subprocess.run(['ip', 'addr', 'show'], capture_output=True, text=True)
        lines = result.stdout.split('\n')
        for line in lines:
            if 'inet ' in line and 'scope global' in line:
                ip = line.strip().split()[1].split('/')[0]
                # 过滤掉回环地址
                if not ip.startswith('127.'):
                    ips.append(ip)
    except Exception:
        # 如果ip命令失败，使用socket方法获取主要IP
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
                s.connect(("8.8.8.8", 80))
                primary_ip = s.getsockname()[0]
                if not primary_ip.startswith('127.'):
                    ips.append(primary_ip)
        except Exception:
            pass

    return ips if ips else ["localhost"]


def get_primary_ip():
    """获取主要的局域网IP地址（用于路由到外网的IP）"""
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
            s.connect(("8.8.8.8", 80))
            return s.getsockname()[0]
    except Exception:
        return "localhost"


class UnifiedServer:
    """统一服务器类，管理Web服务和MCP服务的生命周期"""
    
    def __init__(self, config_path: Optional[str] = None):
        """
        初始化统一服务器
        
        Args:
            config_path: 配置文件路径，如果为None则使用默认配置
        """
        # 加载配置
        self.config = load_config(config_path)
        
        # 设置日志
        setup_logging(self.config.logging)
        
        # 初始化组件
        self.model: Optional[YOLO11_FaceDetect] = None
        self.web_service: Optional[WebService] = None
        self.mcp_service: Optional[MCPService] = None
        
        # 控制标志
        self.running = False
        self.web_thread: Optional[threading.Thread] = None
        
        logger.info("统一服务器初始化完成")
    
    def initialize_model(self):
        """初始化YOLO人脸检测模型"""
        try:
            logger.info("正在加载YOLO人脸检测模型...")
            model_path = self.config.model.path
            conf_thres = self.config.model.confidence_threshold
            iou_thres = self.config.model.iou_threshold
            
            self.model = YOLO11_FaceDetect(
                settings=self.config,
                model_path=model_path,
                conf_threshold=conf_thres,
                iou_threshold=iou_thres,
            )
            logger.info("YOLO人脸检测模型加载成功")
            
        except Exception as e:
            logger.error(f"模型加载失败: {e}")
            raise
    
    def initialize_services(self):
        """初始化Web服务和MCP服务"""
        try:
            # 初始化Web服务
            logger.info("正在初始化Web服务...")
            self.web_service = WebService(
                model=self.model,
                config=self.config
            )
            logger.info("Web服务初始化成功")
            
            # 初始化MCP服务
            logger.info("正在初始化MCP服务...")
            self.mcp_service = MCPService(
                web_service_url=f"http://{self.config.web.host}:{self.config.web.port}",
                config=self.config
            )
            logger.info("MCP服务初始化成功")
            
        except Exception as e:
            logger.error(f"服务初始化失败: {e}")
            raise
    
    def start_web_service(self):
        """在单独线程中启动Web服务"""
        def run_web():
            try:
                logger.info(f"启动Web服务: http://{self.config.web.host}:{self.config.web.port}")
                self.web_service.run()
            except Exception as e:
                logger.error(f"Web服务运行错误: {e}")
        
        self.web_thread = threading.Thread(target=run_web, daemon=True)
        self.web_thread.start()
        
        # 等待Web服务启动
        time.sleep(2)
        logger.info("Web服务已在后台启动")
    
    async def start_mcp_service(self):
        """启动MCP服务（异步）"""
        try:
            logger.info(f"启动MCP服务: http://{self.config.mcp.host}:{self.config.mcp.port}")
            await self.mcp_service.run()
        except Exception as e:
            logger.error(f"MCP服务运行错误: {e}")
            raise
    
    async def start(self):
        """启动统一服务器"""
        try:
            self.running = True

            # 1. 初始化模型
            self.initialize_model()

            # 2. 初始化服务
            self.initialize_services()

            # 3. 启动Web服务（后台线程）
            self.start_web_service()

            # 4. 显示启动信息
            logger.info("统一服务器启动完成")
            logger.info("=" * 50)
            logger.info("服务访问地址:")

            # 显示本地访问地址
            logger.info(f"  Web界面 (本地): http://127.0.0.1:{self.config.web.port}")
            logger.info(f"  MCP服务 (本地): http://127.0.0.1:{self.config.mcp.port}/mcp/")

            # 如果配置为监听所有接口，显示所有局域网访问地址
            if self.config.web.host == "0.0.0.0":
                local_ips = get_local_ips()
                primary_ip = get_primary_ip()

                if local_ips and local_ips != ["localhost"]:
                    logger.info("  局域网访问地址:")
                    for ip in local_ips:
                        # 标记主要IP（用于路由到外网的IP）
                        marker = " (主要)" if ip == primary_ip else ""
                        logger.info(f"    Web界面: http://{ip}:{self.config.web.port}{marker}")
                        logger.info(f"    MCP服务: http://{ip}:{self.config.mcp.port}/mcp/{marker}")

            logger.info("=" * 50)

            # 5. 启动MCP服务（主线程，阻塞运行）
            await self.start_mcp_service()

        except Exception as e:
            logger.error(f"服务器启动失败: {e}")
            await self.stop()
            raise
    
    async def stop(self):
        """停止统一服务器"""
        logger.info("正在停止统一服务器...")
        self.running = False

        try:
            # 停止MCP服务
            if self.mcp_service:
                await self.mcp_service.stop()

            # 停止Web服务
            if self.web_service:
                self.web_service.stop()

            # 等待Web线程结束
            if self.web_thread and self.web_thread.is_alive():
                logger.info("等待Web服务线程结束...")
                self.web_thread.join(timeout=5.0)
                if self.web_thread.is_alive():
                    logger.warning("Web服务线程未能在5秒内结束")

            logger.info("统一服务器已停止")

        except Exception as e:
            logger.error(f"停止服务器时出错: {e}")
            # 强制退出
            import os
            os._exit(1)


# 全局服务器实例
unified_server: Optional[UnifiedServer] = None
shutdown_event = asyncio.Event()


def signal_handler(sig, frame):
    """处理Ctrl+C信号"""
    logger.info('接收到停止信号，正在关闭服务器...')
    # 设置关闭事件，让主循环处理停止操作
    if shutdown_event:
        shutdown_event.set()
    else:
        # 如果事件未初始化，直接退出
        sys.exit(0)


def create_unified_server(config_path: Optional[str] = None) -> UnifiedServer:
    """
    创建统一服务器实例
    
    Args:
        config_path: 配置文件路径
        
    Returns:
        UnifiedServer实例
    """
    return UnifiedServer(config_path)


async def main():
    """主函数"""
    global unified_server, shutdown_event

    # 解析命令行参数
    import argparse
    parser = argparse.ArgumentParser(description="智能人脸追踪系统 - 统一MCP服务器")
    parser.add_argument("--config", "-c", help="配置文件路径")
    args = parser.parse_args()

    # 初始化关闭事件
    shutdown_event = asyncio.Event()

    # 注册信号处理函数
    def signal_handler_async(sig, frame):
        logger.info(f'接收到信号 {sig}，正在关闭服务器...')
        shutdown_event.set()

    signal.signal(signal.SIGINT, signal_handler_async)
    signal.signal(signal.SIGTERM, signal_handler_async)

    try:
        # 创建并启动统一服务器
        unified_server = create_unified_server(config_path=args.config)

        # 在后台启动服务器
        server_task = asyncio.create_task(unified_server.start())

        # 等待关闭信号或服务器完成
        try:
            done, pending = await asyncio.wait(
                [server_task, asyncio.create_task(shutdown_event.wait())],
                return_when=asyncio.FIRST_COMPLETED,
                timeout=None
            )

            # 取消未完成的任务
            for task in pending:
                task.cancel()
                try:
                    await asyncio.wait_for(task, timeout=2.0)
                except (asyncio.CancelledError, asyncio.TimeoutError):
                    logger.info("任务已取消或超时")

        except Exception as e:
            logger.error(f"等待任务时出错: {e}")

    except KeyboardInterrupt:
        logger.info("程序被用户中断")
        shutdown_event.set()
    except Exception as e:
        logger.error(f"程序出错: {str(e)}")
        shutdown_event.set()
    finally:
        if unified_server:
            try:
                await asyncio.wait_for(unified_server.stop(), timeout=10.0)
            except asyncio.TimeoutError:
                logger.warning("服务器停止超时，强制退出")
                import os
                os._exit(1)
            except Exception as e:
                logger.error(f"停止服务器时出错: {e}")
                import os
                os._exit(1)


if __name__ == "__main__":
    asyncio.run(main())
